#include <sys/spinlock.h>
#include <sys/proc.h>
#include <sys/syscall.h>
#include <arch/xchg.h>
#include <ctype.h>
#include <types.h>
#include <errno.h>

int spin_lock_init(spinlock_t *lock)
{
    if (!lock)
        return EINVAL;
    lock->lock = 0;
    return 0;
}

int spin_lock(spinlock_t *lock)
{
    int i;

    if (!lock)
        return EINVAL;

    while (1)
    {
        for (i = 0; i < __SPIN_COUNT; i++)
        {
            if (!spin_trylock(lock))
            {
                return 0;
            }
        }
        sched_yeild();
    }
    return EBUSY;
}

int spin_trylock(spinlock_t *lock)
{
    uint32_t old;

    if (!lock)
        return EINVAL;

    old = test_and_set(&lock->lock, 1);
    if (old)
        return 0;
    else
        return EBUSY;
}

int spin_unlock(spinlock_t *lock)
{
    if (!lock)
        return EINVAL;
    lock->lock = 0;
    return 0;
}

int spin_is_lock(spinlock_t *lock)
{
    if (!lock)
        return EINVAL;
    return lock->lock;
}
